package com.github.tonydeng.fmj.handler;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.system.SystemUtil;
import cn.hutool.system.oshi.OshiUtil;
import com.github.tonydeng.fmj.pool.RedisOpsUtil;
import com.github.tonydeng.fmj.runner.BaseChiaCommandOption;
import com.google.common.collect.Lists;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import oshi.hardware.NetworkIF;

import java.io.*;
import java.util.List;

/**
 * Created by tonydeng on 15/4/20.
 */
@Slf4j
public class DefaultCallbackHandler implements ProcessCallbackHandler {

    @Override
    public String handler(String workId, String dCount, InputStream inputStream, RedisOpsUtil redisOpsUtil) throws IOException {
        @Cleanup BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, BaseChiaCommandOption.UTF8));
        List<String> buffer = Lists.newArrayList();
        String line;

        //使用的硬盘目录
        String usedDisk = redisOpsUtil.getValue("tmpDir" + dCount);
        while ((line = reader.readLine()) != null) {
            try {
                buffer.add(line);

                FileWriter writer2 = new FileWriter("/home/chia/diskFullLog/" + workId + ".log");
                writer2.append(line);
                writer2.append("\n");

                //根据输出日志来判断该进程是否还在工作，工作证明延迟5分钟
                redisOpsUtil.setValue("working_" + dCount + "_" + workId, "1", 300L);

                String diskLog = redisOpsUtil.getValue("diskLog_" + workId);
                if (StrUtil.isEmpty(diskLog)) {
                    FileWriter writer = new FileWriter("/home/chia/diskLog/" + workId + ".log");

                    File diskPartition = new File(usedDisk);
                    long totalCapacity = diskPartition.getTotalSpace();
                    long usablePatitionSpace = diskPartition.getUsableSpace();

                    String tempDir = redisOpsUtil.getValue("tempDir_"+ workId);
                    long totalTempCapacity = FileUtil.size(new File(tempDir));

                    String logTime = DateUtil.now();
                    String logStr = StrUtil.format("{}:workId:{},diskCount:{},Total disk size : {}, Usable Space : {}, tempDir used Space : {}", logTime, workId, dCount, FileUtil.readableFileSize(totalCapacity), FileUtil.readableFileSize(usablePatitionSpace), FileUtil.readableFileSize(totalTempCapacity));
                    writer.append(logStr);
                    writer.append("\n");

                    //内存使用情况
                    long totalMemory = OshiUtil.getMemory().getTotal();
                    long availableMemory = OshiUtil.getMemory().getAvailable();
                    String logStr2 = StrUtil.format("{}:totalMemory:{}, availableMemory:{}", logTime, FileUtil.readableFileSize(totalMemory), FileUtil.readableFileSize(availableMemory));
//                    writer.append(logStr2);
//                    writer.append("\n");

                    //获取cpu温度, 风扇速度
//                    String logStr3 = StrUtil.format("{}: CpuTemperature:{}, FanSpeeds:{}", logTime, OshiUtil.getSensors().getCpuTemperature(), OshiUtil.getSensors().getFanSpeeds());
//                    writer.append(logStr3);
//                    writer.append("\n");

                    //获取cpu信息
//                    String logStr4 = OshiUtil.getCpuInfo().toString();
//                    writer.append(logStr4);
//                    writer.append("\n");

                    if (log.isInfoEnabled()){
                        log.info("chia disk log : '{}'", logStr);
                        log.info("chia memory log : '{}'", logStr2);
                    }

//                    if (log.isDebugEnabled()){
//                        log.info("chia cpu1 log : '{}'", logStr3);
//                        log.info("chia cpu2 log : '{}'", logStr4);
//                    }

                    //获取网络传输
//                    List<NetworkIF> list = OshiUtil.getNetworkIFs();
//                    for (NetworkIF netWorkIf:list
//                         ) {
//                        String logStr5 = StrUtil.format("{}:{},Recv:{},Sent:{},Speed:{}", logTime, netWorkIf.getDisplayName(), FileUtil.readableFileSize(netWorkIf.getBytesRecv()), FileUtil.readableFileSize(netWorkIf.getBytesSent()), FileUtil.readableFileSize(netWorkIf.getSpeed()));
//                        writer.append(logStr5);
//                        writer.append("\n");
//                        if (log.isDebugEnabled()){
//                            log.info("chia netWork log : '{}'", logStr5);
//                        }
//                    }

                    redisOpsUtil.setValue("diskLog_" + workId, "1", 60L);
                }

                //实时输出全部日志
                if (log.isDebugEnabled()) {
                    log.debug("chia workId {} process... log : '{}'", workId, line);
                } else if (log.isInfoEnabled()) { //实时输出阶段信息日志
                    if (line.contains("Computing table") || line.contains("time") || line.contains("table") || line.contains("phase") || line.contains("Total time")) {
                        FileWriter writer = new FileWriter("/home/chia/diskLog/" + workId + ".log");
                        writer.append(StrUtil.format("{}:{}", DateUtil.now(), line));
                        writer.append("\n");
                        log.info("chia workId {} process... log : '{}'", workId, line);
                    }

                    if (line.contains("Time for phase 1")) {
                        redisOpsUtil.setValue("plot_phase_1_" + dCount + "_" + workId, "1");
                        String time = ReUtil.get("Time for phase 1 = .* seconds", line, 0);
                        redisOpsUtil.setValue("plot_phase_1_time_" + dCount + "_" + workId, time.replace("Time for phase 1 = ", "").replace(" seconds", ""));
                    } else if (line.contains("Time for phase 2")) {
                        redisOpsUtil.setValue("plot_phase_2_" + dCount + "_" + workId, "1");
                        String time = ReUtil.get("Time for phase 2 = .* seconds", line, 0);
                        redisOpsUtil.setValue("plot_phase_2_time_" + dCount + "_" + workId, time.replace("Time for phase 2 = ", "").replace(" seconds", ""));
                    } else if (line.contains("Time for phase 3")) {
                        redisOpsUtil.setValue("plot_phase_3_" + dCount + "_" + workId, "1");
                        String time = ReUtil.get("Time for phase 3 = .* seconds", line, 0);
                        redisOpsUtil.setValue("plot_phase_3_time_" + dCount + "_" + workId, time.replace("Time for phase 3 = ", "").replace(" seconds", ""));
                    } else if (line.contains("Time for phase 4")) {
                        redisOpsUtil.setValue("plot_phase_4_" + dCount + "_" + workId, "1");
                        String time = ReUtil.get("Time for phase 4 = .* seconds", line, 0);
                        redisOpsUtil.setValue("plot_phase_4_time_" + dCount + "_" + workId, time.replace("Time for phase 4 = ", "").replace(" seconds", ""));
                    } else if (line.contains("Total time")) {
                        String time = ReUtil.get("Total time = .* seconds", line, 0);
                        redisOpsUtil.setValue("plot_phase_total_time_" + dCount + "_" + workId, time.replace("Total time = ", "").replace(" seconds", ""));
                    }
                }
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
        return String.join("\n", buffer);
    }
}
